<script setup>
// 导入自定义输入组件：线性布局和水平布局的输入框
import ULEdittext from '@/widget/ULinearEditext.vue';
import UHEdittext from '@/widget/UHorEditext.vue';
// 导入Vue核心API：创建VNode、获取组件实例、计算属性、依赖注入、Props定义
import { getCurrentInstance, computed, inject, defineProps } from 'vue';

/**
 * 表单项组件Props定义
 * @property {Boolean} horizontal - 是否水平布局（默认false）
 * @property {String} prop - 绑定的表单字段名（必填）
 */
const props = defineProps({
  horizontal: {
    type: Boolean,
    default: false,
    description: '是否使用水平布局，默认垂直布局'
  },
  prop: {
    type: String,
    required: true,
    description: '绑定的表单字段名，用于表单验证和数据绑定'
  }
});

/**
 * 根据布局类型动态选择输入组件
 * @returns 0 水平布局返回UHEdittext，垂直布局返回ULEdittext
 */
const ElInput = computed(() => (props.horizontal ? UHEdittext : ULEdittext));

// 获取当前组件实例（用于暴露子组件引用）
const vm = getCurrentInstance();
// 从父组件注入表单上下文（BaseForm提供的formState）
const form = inject('form'); // 注入表单上下文

/**
 * 处理输入组件引用并注册表单字段
 * @param {Object} inputInstance - 输入组件实例
 * @description 当输入组件挂载时调用，将字段注册到表单，并暴露组件实例
 */
function changRef(inputInstance) {
  // 暴露子组件实例给父组件
  vm.exposed = vm.exposeProxy = inputInstance || {};
  // 如果表单上下文存在且提供了注册方法，则注册当前字段
  if (form && form.registerField) {
    form.registerField({
      key: props.prop, // 字段名，对应表单数据的key
      getValue() {
        // 直接从表单模型获取值，确保与表单数据同步
        // 避免依赖子组件暴露的值，提高数据一致性
        return form.model[props.prop];
      }
    });
  }
}
</script>
<!--自带了-->
<template>
  <div class="form-item">
    <!-- 优先使用用户提供的插槽内容（自定义表单控件） -->
    <template v-if="$slots.default">
      <slot></slot>
    </template>
    <ElInput v-else v-bind="{ ...$attrs, ...props }" :ref="changRef">
      <!-- 透传所有插槽内容到输入组件 -->
      <template v-for="(_, name) in $slots" #[name]="slotData">
        <slot :name="name" v-bind="slotData"></slot>
      </template>
    </ElInput>
    <!-- 错误信息显示：当表单验证失败时显示 -->
    <span v-if="form.errors[prop]" class="error-message">{{ form.errors[prop] }}</span>
  </div>
</template>

<style lang="less" scoped>
/* 必填项标记样式 */
.required-mark {
  color: #ff4d4f; /* 错误红色 */
  margin-left: 4px;
}

/* 错误信息样式 */
.error-message {
  color: #ff4d4f; /* 错误红色 */
  font-size: 12px; /* 小号字体 */
  margin-left: 15px; /* 与输入框保持间距 */
}
</style>
